﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using ReLogic.IO;
using ReLogic.OS;
using Terraria.Initializers;
using Terraria.Localization;
using Terraria.ModLoader;
using Terraria.Social;
using Terraria.Utilities;

namespace Terraria
{
	// Token: 0x0200003E RID: 62
	public static class Program
	{
		// Token: 0x170000B0 RID: 176
		// (get) Token: 0x0600061D RID: 1565 RVA: 0x00008ED1 File Offset: 0x000070D1
		public static float LoadedPercentage
		{
			get
			{
				if (Program.ThingsToLoad == 0)
				{
					return 1f;
				}
				return (float)Program.ThingsLoaded / (float)Program.ThingsToLoad;
			}
		}

		// Token: 0x0600061E RID: 1566 RVA: 0x00008EED File Offset: 0x000070ED
		public static void StartForceLoad()
		{
			if (!Main.SkipAssemblyLoad)
			{
				ThreadPool.QueueUserWorkItem(new WaitCallback(Program.ForceLoadThread));
				return;
			}
			Program.LoadedEverything = true;
		}

		// Token: 0x0600061F RID: 1567 RVA: 0x00008F0F File Offset: 0x0000710F
		public static void ForceLoadThread(object ThreadContext)
		{
			Program.ForceLoadAssembly(Assembly.GetExecutingAssembly(), true);
			Program.LoadedEverything = true;
		}

		// Token: 0x06000620 RID: 1568 RVA: 0x002AAEC0 File Offset: 0x002A90C0
		private static void ForceJITOnAssembly(Assembly assembly)
		{
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!methodInfo.IsAbstract && !methodInfo.ContainsGenericParameters && methodInfo.GetMethodBody() != null)
					{
						RuntimeHelpers.PrepareMethod(methodInfo.MethodHandle);
					}
				}
				Program.ThingsLoaded++;
			}
		}

		// Token: 0x06000621 RID: 1569 RVA: 0x002AAF44 File Offset: 0x002A9144
		private static void ForceStaticInitializers(Assembly assembly)
		{
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (!type.IsGenericType)
				{
					RuntimeHelpers.RunClassConstructor(type.TypeHandle);
				}
			}
		}

		// Token: 0x06000622 RID: 1570 RVA: 0x00008F22 File Offset: 0x00007122
		private static void ForceLoadAssembly(Assembly assembly, bool initializeStaticMembers)
		{
			Program.ThingsToLoad = assembly.GetTypes().Length;
			Program.ForceJITOnAssembly(assembly);
			if (initializeStaticMembers)
			{
				Program.ForceStaticInitializers(assembly);
			}
		}

		// Token: 0x06000623 RID: 1571 RVA: 0x002AAF80 File Offset: 0x002A9180
		private static void ForceLoadAssembly(string name, bool initializeStaticMembers)
		{
			Assembly assembly = null;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			for (int i = 0; i < assemblies.Length; i++)
			{
				if (assemblies[i].GetName().Name.Equals(name))
				{
					assembly = assemblies[i];
					break;
				}
			}
			if (assembly == null)
			{
				assembly = Assembly.Load(name);
			}
			Program.ForceLoadAssembly(assembly, initializeStaticMembers);
		}

		// Token: 0x06000624 RID: 1572 RVA: 0x002AAFDC File Offset: 0x002A91DC
		private static void SetupLogging()
		{
			bool flag = Program.LaunchParameters.ContainsKey("-logfile");
			if (flag)
			{
				string text = Program.LaunchParameters["-logfile"];
				if (text == null || text.Trim() == "")
				{
					text = Path.Combine(Main.SavePath, "Logs", string.Format("Log_{0}.log", DateTime.Now.ToString("yyyyMMddHHmmssfff")));
				}
				else
				{
					text = Path.Combine(text, string.Format("Log_{0}.log", DateTime.Now.ToString("yyyyMMddHHmmssfff")));
				}
				ConsoleOutputMirror.ToFile(text);
			}
			if (Program.LaunchParameters.ContainsKey("-logerrors"))
			{
				Program.HookAllExceptions();
			}
		}

		// Token: 0x06000625 RID: 1573 RVA: 0x002AB090 File Offset: 0x002A9290
		private static void HookAllExceptions()
		{
			bool useMiniDumps = Program.LaunchParameters.ContainsKey("-minidump");
			bool useFullDumps = Program.LaunchParameters.ContainsKey("-fulldump");
			Console.WriteLine("Error Logging Enabled.");
			CrashDump.Options dumpOptions = CrashDump.Options.WithFullMemory;
			if (useFullDumps)
			{
				Console.WriteLine("Full Dump logs enabled.");
			}
			AppDomain.CurrentDomain.FirstChanceException += delegate(object sender, FirstChanceExceptionEventArgs exceptionArgs)
			{
				string arg = exceptionArgs.Exception.ToString();
				string text = "================\r\n";
				text += string.Format("{0}: First-Chance Exception\r\nCulture: {1}\r\nException: {2}\r\n", DateTime.Now, Thread.CurrentThread.CurrentCulture.Name, arg);
				text += "================\r\n\r\n";
				Console.Write(text);
				if (useMiniDumps)
				{
					CrashDump.WriteException(CrashDump.Options.WithIndirectlyReferencedMemory, Path.Combine(Main.SavePath, "Dumps"));
				}
			};
			AppDomain.CurrentDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs exceptionArgs)
			{
				string arg = exceptionArgs.ExceptionObject.ToString();
				string text = "================\r\n";
				text += string.Format("{0}: Unhandled Exception\r\nCulture: {1}\r\nException: {2}\r\n", DateTime.Now, Thread.CurrentThread.CurrentCulture.Name, arg);
				text += "================\r\n";
				Console.Write(text);
				if (useFullDumps)
				{
					CrashDump.WriteException(dumpOptions, Path.Combine(Main.SavePath, "Dumps"));
				}
			};
		}

		// Token: 0x06000626 RID: 1574 RVA: 0x002AB11C File Offset: 0x002A931C
		private static void InitializeConsoleOutput()
		{
			if (Debugger.IsAttached)
			{
				return;
			}
			try
			{
				Console.OutputEncoding = Encoding.UTF8;
				if (Platform.IsWindows)
				{
					Console.InputEncoding = Encoding.Unicode;
				}
				else
				{
					Console.InputEncoding = Encoding.UTF8;
				}
			}
			catch
			{
			}
		}

		// Token: 0x06000627 RID: 1575 RVA: 0x002AB170 File Offset: 0x002A9370
		public static void LaunchGame(string[] args, bool monoArgs = false)
		{
			if (monoArgs)
			{
				args = Utils.ConvertMonoArgsToDotNet(args);
			}
			if (Platform.IsOSX)
			{
				Main.OnEngineLoad += delegate
				{
					Main.instance.IsMouseVisible = false;
				};
			}
			Program.LaunchParameters = Utils.ParseArguements(args);
			if (Program.LaunchParameters.ContainsKey("-savedirectory"))
			{
				Program.LaunchParameters["-savedirectory"] = Path.Combine(Program.LaunchParameters["-savedirectory"], "ModLoader");
			}
			ErrorLogger.ClearLogs();
			if (Program.LaunchParameters.ContainsKey("-build"))
			{
				ModCompile.BuildModCommandLine(Program.LaunchParameters["-build"]);
				return;
			}
			ThreadPool.SetMinThreads(8, 8);
			LanguageManager.Instance.SetLanguage(GameCulture.English);
			Program.SetupLogging();
			using (Main main = new Main())
			{
				try
				{
					Program.InitializeConsoleOutput();
					Lang.InitializeLegacyLocalization();
					SocialAPI.Initialize(null);
					LaunchInitializer.LoadParameters(main);
					Main.OnEnginePreload += Program.StartForceLoad;
					main.Run();
				}
				catch (Exception e)
				{
					Program.DisplayException(e);
				}
			}
		}

		// Token: 0x06000628 RID: 1576 RVA: 0x002AB2AC File Offset: 0x002A94AC
		private static void DisplayException(Exception e)
		{
			try
			{
				using (StreamWriter streamWriter = new StreamWriter("client-crashlog.txt", true))
				{
					streamWriter.WriteLine(DateTime.Now);
					streamWriter.WriteLine(e);
					streamWriter.WriteLine("");
				}
				MessageBox.Show(e.ToString(), "Terraria: Error");
				if (e.Message.Contains("CSteamworks"))
				{
					Process.Start("https://github.com/blushiemagic/tModLoader/wiki/Basic-tModLoader-Usage-FAQ#systemdllnotfoundexception-unable-to-load-dllcsteamworks");
				}
				if (e.StackTrace.Contains("LaunchLocalServer"))
				{
					MessageBox.Show("Looks like you didn't do a complete install. You are missing tModLoaderServer.exe. Check your install directory and read the install directions.", "Terraria: Error");
					Process.Start("https://github.com/blushiemagic/tModLoader/wiki/Basic-tModLoader-Usage-FAQ#host-and-play-the-system-cannot-find-the-file-specified");
				}
			}
			catch
			{
			}
		}

		// Token: 0x04000C2E RID: 3118
		public const bool IsServer = false;

		// Token: 0x04000C2F RID: 3119
		public static Dictionary<string, string> LaunchParameters = new Dictionary<string, string>();

		// Token: 0x04000C30 RID: 3120
		private static int ThingsToLoad = 0;

		// Token: 0x04000C31 RID: 3121
		private static int ThingsLoaded = 0;

		// Token: 0x04000C32 RID: 3122
		public static bool LoadedEverything = false;

		// Token: 0x04000C33 RID: 3123
		public static IntPtr JitForcedMethodCache;
	}
}
